/*******************************************************************************
 * Copyright (c) 2008-2010 Cedric Vidal
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Cedric Vidal - original idea, initial contribution and API
 *******************************************************************************/

package org.trans4j.impl;

import java.util.HashMap;
import java.util.Map;

import net.sf.cglib.proxy.Proxy;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author <a href="mailto:c.vidal@proxiad.com">Cedric Vidal, ProxiAD Group</a>
 * 
 */
public class CacheSupport<K, V> {

	private Log log = LogFactory.getLog(getClass());

	private static final ThreadLocal<Map<Object, Object>> cacheThreadLocal = new ThreadLocal<Map<Object, Object>>();

	protected final V cached(K key) {
		Map<K, V> cache = cache();
		return (V) cache.get(key);
	}

	protected final void init() {
		cache();
	}

	@SuppressWarnings("unchecked")
	private Map<K, V> cache() {
		Map<K, V> cache = (Map<K, V>) cacheThreadLocal.get();
		if (cache == null) {
			cache = new HashMap<K, V>();
			cacheThreadLocal.set((Map<Object, Object>) cache);
		}
		return cache;
	}

	protected void releaseCache() {
		log.debug("Releasing cache " + cacheThreadLocal.get());
		cacheThreadLocal.remove();
	}

	protected boolean isCacheActive() {
		return cacheThreadLocal.get() != null;
	}

	protected boolean isCached(Object key) {
		return cache().containsKey(key);
	}

	protected void cache(K key, V object) {
		if (log.isDebugEnabled()) {
			if (Proxy.isProxyClass(object.getClass())) {
				log.debug("Caching " + key + " -> proxy for "
						+ object.getClass());
			} else {
				log.debug("Caching " + key + " -> " + object);
			}
		}
		Map<K, V> cache = cache();
		cache.put(key, object);
	}

}
